package extension.game.room;

import com.smartfoxserver.v2.entities.Room;
import com.smartfoxserver.v2.entities.User;
import extension.game.room.handler.RoomFlag;
import extension.game.zone.GameZoneExtension;
import extension.room.analyse.Card;
import extension.room.analyse.CardDealer;
import java.util.LinkedList;
import java.util.List;
import log.Debug;

/**
 *
 * @author daz
 */
public abstract class Game implements Runnable {

    protected int maxPlayer = 4;
    protected int numberDealCard = 9;
    protected boolean isPlay;
    protected int gameTurn;
    protected int tableHost;
    protected int numberPlayers;
    protected int numberPlayings;
    protected long betMoney;
    protected int numberWaiting;
    protected boolean isRunning;
    protected Room room;
    protected long betMin;
    protected int winnerId;
    protected long penaltyMoney;
    protected boolean isHostTimeOut;
    protected final CardDealer dealer;
    public static final int[] listRoomBet = {10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000};
    protected int numberInRooms;

    public Game(Room room, int roomId) {
        dealer = new CardDealer();
        this.room = room;
        winnerId = -1;
        setRoomBetMin(listRoomBet[(roomId - 1) / GameZoneExtension.numberTablePerRooms]);
        List<Integer> listLevelBet = new LinkedList<Integer>();

//        for (int i = 0, l = GameZoneExtension.numberTable / GameZoneExtension.numberTablePerRooms; i < l; i++) {
//                                
//        }
//        if (roomId < 11) {
//            setRoomBetMin(10);
//        } else if (roomId < 21) {
//            setRoomBetMin(20);
//        } else if (roomId < 31) {
//            setRoomBetMin(50);
//        } else if (roomId < 41) {
//            setRoomBetMin(100);
//        } else if (roomId < 51) {
//            setRoomBetMin(200);
//        } else if (roomId < 61) {
//            setRoomBetMin(500);
//        } else if (roomId < 71) {
//            setRoomBetMin(1000);
//        } else if (roomId < 81) {
//            setRoomBetMin(2000);
//        } else if (roomId < 91) {
//            setRoomBetMin(5000);
//        } else if (roomId < 101) {
//            setRoomBetMin(10000);
//        } else {
//            setRoomBetMin(100000);
//        }
    }

    private void setRoomBetMin(long money) {
        betMin = money;
        betMoney = betMin;
        room.setProperty(RoomFlag.BET_MIN, betMin);
        room.setProperty(RoomFlag.BET_MONEY, money);
    }

    public void start() {
        if (!isRunning) {
            isRunning = true;
            new Thread(this).start();
        }
    }

    public long getBetMin() {
        return betMin;
    }

    public int getMaxPlayer() {
        return maxPlayer;
    }

    public abstract Player addPlayer(String name, long money, User user);

    protected abstract void addTableInfo();

    protected abstract void sendTableInfo(String roomName, List<String> listNames, List<Integer> listPlayerPos, List<User> listUser);

    public boolean getIsPlay() {
        return isPlay;
    }

    public int getTableHost() {
        return tableHost;
    }

    public void setBetMoney(int betMoney) {
        this.betMoney = betMin * betMoney;
        room.setProperty(RoomFlag.BET_MONEY, this.betMoney);
        checkAllowPlay();
    }

    public abstract void updateReadyState();

    public long getBetMoney() {
        return betMoney;
    }

    public abstract long removePlayer(int leaveId);

    public abstract void sendTimeCount(int tableHost);

    public abstract void updateTableHost();

    public abstract void sendUpdateTableHost(int x, int y);

    @Override
    public void run() {
        while (isRunning) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            doLoop();
        }
    }

    public abstract void doLoop();

    public abstract int changePlayerState(int readyId);

    public abstract int countNumberReady();

    public void startGame() {
        if (!isPlay) {
            int numberReadys = countNumberReady();
            Debug.d("number ready :" + numberReadys);
            Debug.d("number playing :" + numberPlayings);

            if (numberReadys == numberPlayings && numberPlayings > 1) {
                isPlay = true;
            }
            if (isPlay) {
                isHostTimeOut = false;
                dealCard();
            }
        }
    }

    public abstract void dealCard();

    public abstract void updateNumberPlaying();

    public abstract void updateNumberInRoom();

    public int getNumberPlayings() {
        return numberPlayings;
    }

    public int getNumberPlayers() {
        return numberPlayers;
    }

    public abstract void nextTurn();

    public int getGameTurn() {
        return gameTurn;
    }

    protected abstract void checkAllowPlay();

    protected abstract void sendPlayerKick(String playerName, int playerPos, User user);

    public boolean canHostReady() {
        if (numberPlayings == 1) {
            return false;
        }
        int numberReadys = countNumberReady();
        if (numberReadys == numberPlayings - 1) {
            return true;
        }
        return false;
    }

    protected abstract void updateDatabase();

    public abstract void doReady();

    public void setIsHostTimeOut(boolean isHostTimeOut) {
        this.isHostTimeOut = isHostTimeOut;
    }

    public boolean getIsHostTimeOut() {
        return isHostTimeOut;
    }

    public void logShowSet(String name, List<Integer> listPhom) {
        if (listPhom != null && !listPhom.isEmpty()) {
            StringBuilder builder = new StringBuilder();
            for (Integer card : listPhom) {
                builder.append(Card.getName(card));
                builder.append(",");
            }
            Debug.d(name + "-card:" + builder.toString());
        }
    }

    public int getNumberInRooms() {
        return numberInRooms;
    }

    public abstract Player[] getListPlayers();

    public abstract void sendTableInfo(List<String> listNames, List<Long> listMoneys, List<Integer> listStates, Player player, User user);

    public abstract void updateTableInfo(List<String> listNames, List<Long> listMoneys, List<Integer> listStates, Player player);
}
